package netty.demo_02_taskqueue;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;


/**
 * TaskQueue 任务队列部分的示例
 * 这个 Handler 在 demo_01_simple/NettyServer 中调用
 *
 * @author chenyuan
 * @date 2020/11/6 17:58
 */
public class NettyServerHandlerTaskQ extends ChannelInboundHandlerAdapter {
	/**
	 * 读取数据的事件（可以读取客户端发送的消息）
	 *
	 * @param ctx 上下文对象，包含 管道、通道、地址
	 * @param msg 客户端发送的消息，默认是 Object 类型
	 * @throws Exception
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		// 比如这里有一个非常耗时的任务，希望可以异步执行
		// 把该任务提交到 Channel 对应的 NIOEventLoop 的 TaskQueue 中


		// 解决方案-1：用户程序自定义的普通任务
		// 把该任务提交到 Channel 对应的 NIOEventLoop 的 TaskQueue 中
//        ctx.channel().eventLoop().execute(()->{
//            try {
//                Thread.sleep(5 * 1000);
//                ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,客户端，这是一个执行耗时长的任务,方案-1",CharsetUtil.UTF_8));
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        });
//        System.out.println("耗时长的任务执行完毕，继续");


		// 解决方案-2：用户自定义定时任务
		// 把任务提交到 scheduledTaskQueue
        /*
            如果在同一个线程内，任务队列和定时任务同时存在，
            定时任务会在得到连接后就开始计时，
            但是会先执行 TaskQueue 中的任务，再执行 scheduledTaskQueue 中的任务，不论定的时间到没到
         */
		ctx.channel().eventLoop().schedule(() -> {
			try {
				Thread.sleep(5 * 1000);
				ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,客户端，这是一个执行耗时长的任务,方案-2", CharsetUtil.UTF_8));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}, 5, TimeUnit.SECONDS);// 在和服务端连接成功后 5s 开始异步执行 run 方法

		System.out.println("耗时长的任务执行完毕，继续");
	}

	/**
	 * 数据读取完毕后，返回消息给客户端
	 *
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,客户端", CharsetUtil.UTF_8));
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		// 关闭通道
		ctx.channel().close();
	}
}
